﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Security;
using System.Security.Cryptography;

namespace CISExchangeDaemonService
{

    class Manager
    {
        private static bool Current = true;
        /// <summary>
        /// Indeks plikow z danymi
        /// </summary>
        public static string Index = DateTime.Now.ToString("yyyyMMddHHmmss");
        /// <summary>
        /// aktualizuje indeks dla biezacej daty i godziny
        /// </summary>
        public static void UpdateIndex()
        {
            Index = DateTime.Now.ToString("yyyyMMddHHmmss");
        }
        /// <summary>
        /// Dodaje linijke danych do pliku. Jesli plik nie istnieje badz jest uzywany, tworzy nowy plik
        /// </summary>
        /// <param name="data">dane ktore maja zostac dodane do pliku</param>
        /// <returns>Nazwa pliku, do ktorego dodano dane</returns>
        public string AppendDataToFile(string type, string data)
        {
            FileStream filestream;
            string[] temp = data.Split(';');
            string name = temp[0] + " " + temp[1];
            try
            {
                Manager.UpdateIndex();
                filestream = new FileStream(Directory.GetCurrentDirectory() + "\\pending\\" + Manager.Index + "_" + name + ".csv", FileMode.Append, FileAccess.Write, FileShare.None);
            }
            catch
            {
                Manager.UpdateIndex();
                filestream = new FileStream(Directory.GetCurrentDirectory() + "\\pending\\" + Manager.Index + "_" + name + ".csv", FileMode.Append, FileAccess.Write, FileShare.None);
            }
            StreamWriter sw = new StreamWriter(filestream);
            if (type.Equals("add"))
            {
                temp[temp.Length - 1] = Encrypt(temp[temp.Length - 1]);
            }
            StringBuilder sb = new StringBuilder();
            foreach (string s in temp)
            {
                sb.Append(s + ";");
            }
            sw.WriteLine(sb.ToString().Substring(0,sb.ToString().Length-1));
            sw.Close();
            filestream.Close();
            return Manager.Index + "_" + name + ".csv";
        }
        /// <summary>
        /// Wczytuje plik csv i zwraca w postaci listy
        /// </summary>
        /// <param name="filename">Nazwa pliku</param>
        /// <returns>Lista linijek pliku</returns>
        public string LoadFromFile(string filename)
        {
            string data = "";
            FileStream filestr;
            StreamReader sr;
            try
            {
                filestr = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None);
                sr = new StreamReader(filestr);
            }
            catch
            {
                return null;
            }
            string line;
            string[] temp = filename.Split(new char[]{'_', '\\'});
            Int64 file_index = Int64.Parse(temp[temp.Length - 2]);
            Int64 program_start = Int64.Parse(CISExchangeDaemon.startTime.ToString("yyyyMMddHHmmss"));
            while ((line = sr.ReadLine()) != null)
            {
                if (program_start > file_index)
                {
                    Current = false;
                    string[] temp2 = line.Split(';');
                    if (temp2[1].Equals("del"))
                    {
                        data = line;
                        break;
                    }
                    temp2[temp2.Length - 1] = "";
                    StringBuilder sb = new StringBuilder();
                    foreach (string s in temp2)
                    {
                        sb.Append(s + ";");
                    }
                    data = sb.ToString().Substring(0, sb.ToString().Length - 1);
                    break;
                }
                else
                {
                    data = line;
                    break;
                }
            }
            sr.Close();
            filestr.Close();
            return data;
        }

        public string CreateContact(string csv_data)
        {
            Process scriptProc = new Process();
            scriptProc.StartInfo.FileName = @"cscript";
            scriptProc.StartInfo.Arguments = "//Nologo " + "\"" + Directory.GetCurrentDirectory() + "\\scripts\\CreateContact.vbs\" " + "\"" + csv_data + "\"";
            scriptProc.StartInfo.RedirectStandardOutput = true;
            scriptProc.StartInfo.UseShellExecute = false;
            scriptProc.Start();
            string output = scriptProc.StandardOutput.ReadToEnd();
            scriptProc.WaitForExit(5000);
            scriptProc.Close();
            return output;
        }

        /// <summary>
        /// Uruchamia skrypt tworzacy uzytkownika
        /// </summary>
        /// <param name="csv_data">linijka z danymi uzytkownika oddzielonymi ';'</param>
        /// <returns>zwraca wynik dzialania skryptu</returns>
        public string CreateUserAndMailbox(string csv_data, bool current)
        {
            string[] temp = csv_data.Split(';');
            if (!current)
            {
                Process scriptProc = new Process();
                scriptProc.StartInfo.FileName = @"cscript";
                scriptProc.StartInfo.Arguments = "//Nologo " + "\"" + Directory.GetCurrentDirectory() + "\\scripts\\CreateUserNoPassword.vbs\" " + "\"" + csv_data + "\"";
                scriptProc.StartInfo.RedirectStandardOutput = true;
                scriptProc.StartInfo.UseShellExecute = false;
                scriptProc.Start();
                string output = scriptProc.StandardOutput.ReadToEnd();
                scriptProc.WaitForExit(5000);
                scriptProc.Close();
                return output;
            }
            else
            {
                temp[temp.Length - 1] = Decrypt(temp[temp.Length - 1]);
                StringBuilder sb = new StringBuilder();
                foreach (string s in temp)
                {
                    sb.Append(s + ";");
                }
                Process scriptProc = new Process();

                scriptProc.StartInfo.FileName = @"cscript";
                scriptProc.StartInfo.Arguments = "//Nologo " + "\"" + Directory.GetCurrentDirectory() + "\\scripts\\CreateUser.vbs\" " + "\"" + sb.ToString() + "\"";
                scriptProc.StartInfo.RedirectStandardOutput = true;
                scriptProc.StartInfo.UseShellExecute = false;
                scriptProc.Start();
                string output = scriptProc.StandardOutput.ReadToEnd();
                scriptProc.WaitForExit(5000);
                scriptProc.Close();
                return output;
            }
        }
        /// <summary>
        /// uruchamia skrypt kasujacy uzytkownika
        /// </summary>
        /// <param name="csv_data">login uzytkownika</param>
        /// <returns>zwraca wynik dzialania skryptu</returns>
        public string DeleteUser(string csv_data)
        {
            Process scriptProc = new Process();
            scriptProc.StartInfo.FileName = @"cscript";
            scriptProc.StartInfo.Arguments = "//Nologo " + "\"" + Directory.GetCurrentDirectory() + "\\scripts\\RemoveUser.vbs\" " + "\"" + csv_data + "\"";
            scriptProc.StartInfo.RedirectStandardOutput = true;
            scriptProc.StartInfo.UseShellExecute = false;
            scriptProc.Start();
            string output = scriptProc.StandardOutput.ReadToEnd();
            scriptProc.WaitForExit(5000);
            scriptProc.Close();
            return output;
        }

        private static byte[] bytes = Encoding.ASCII.GetBytes(RandomPassword.Generate(8));

        /// <summary>
        /// Szyfruje stringa
        /// </summary>
        /// <param name="originalString"></param>
        /// <returns></returns>
        public string Encrypt(string originalString)
        {
            if (String.IsNullOrEmpty(originalString))
            {
                throw new ArgumentNullException
                       ("The string which needs to be encrypted can not be null.");
            }
            DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                cryptoProvider.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
            StreamWriter writer = new StreamWriter(cryptoStream);
            writer.Write(originalString);
            writer.Flush();
            cryptoStream.FlushFinalBlock();
            writer.Flush();
            return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
        }
        /// <summary>
        /// Deszyfruje stringa
        /// </summary>
        /// <param name="cryptedString"></param>
        /// <returns></returns>
        public string Decrypt(string cryptedString)
        {
            if (String.IsNullOrEmpty(cryptedString))
            {
                throw new ArgumentNullException
                   ("The string which needs to be decrypted can not be null.");
            }
            DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            MemoryStream memoryStream = new MemoryStream
                    (Convert.FromBase64String(cryptedString));
            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                cryptoProvider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read);
            StreamReader reader = new StreamReader(cryptoStream);
            return reader.ReadToEnd();
        }
    }
}
